package com.atguigu.buffer;

import org.junit.jupiter.api.Test;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.RandomAccessFile;
import java.nio.ByteBuffer;
import java.nio.MappedByteBuffer;
import java.nio.channels.FileChannel;
import java.util.Objects;

/**
 * className: BufferDemo2
 * description:
 * date: 2023/3/9 0009-17:44
 * <p>
 * project: nio
 * package: com.atguigu.buffer
 * email: 1085844536@qq.com
 * version:
 *
 * @author WangGuojian
 */
public class BufferDemo2 {

    private static final int START = 0;
    private static final int SIZE = 1024;

    /**
     * 内存映射文件 io
     */
    @Test
    public void b04() throws IOException {
        RandomAccessFile raf = new RandomAccessFile(Objects.requireNonNull(BufferDemo2.class.getClassLoader().getResource("01.txt")).getPath(), "rw");
        FileChannel fc = raf.getChannel();
        MappedByteBuffer mbb = fc.map(FileChannel.MapMode.READ_WRITE, START, SIZE);

        mbb.put(0, (byte) 97);
        mbb.put(1023, (byte) 122);
        raf.close();
    }

    /**
     * 直接缓冲区
     */
    @Test
    public void b03() throws IOException {
        String infile = Objects.requireNonNull(BufferDemo2.class.getClassLoader().getResource("01.txt")).getPath();
        FileInputStream fin = new FileInputStream(infile);
        FileChannel finChannel = fin.getChannel();

        String outfile = Objects.requireNonNull(BufferDemo2.class.getClassLoader().getResource("")).getPath() + "02.txt";
        FileOutputStream fout = new FileOutputStream(outfile);
        FileChannel foutChannel = fout.getChannel();

        // 创建直接缓冲区
        ByteBuffer buffer = ByteBuffer.allocateDirect(1024);

        while (true) {
            buffer.clear();

            int r = finChannel.read(buffer);
            if (r == -1) {
                break;
            }
            buffer.flip();
            foutChannel.write(buffer);
        }
    }

    /**
     * 只读缓冲区
     */
    @Test
    public void b02() {
        ByteBuffer buffer = ByteBuffer.allocate(10);

        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte) i);
        }

        // 创建只读缓冲区
        ByteBuffer readonly = buffer.asReadOnlyBuffer();

        for (int i = 0; i < buffer.capacity(); i++) {
            byte b = buffer.get(i);
            b *= 10;
            buffer.put(i, b);
        }

        readonly.position(0);
        readonly.limit(buffer.capacity());

        while (readonly.remaining() > 0) {
            System.out.println(readonly.get());
        }
    }

    /**
     * 缓冲区分片
     */
    @Test
    public void b01() {
        ByteBuffer buffer = ByteBuffer.allocate(10);

        for (int i = 0; i < buffer.capacity(); i++) {
            buffer.put((byte) i);
        }

        // 创建子缓冲区
        buffer.position(3);
        buffer.limit(7);
        ByteBuffer slice = buffer.slice();

        // 改变子缓冲区内容
        for (int i = 0; i < slice.capacity(); i++) {
            byte b = slice.get();
            b *= 10;
            slice.put(i, b);
        }

        buffer.position(0);
        buffer.limit(buffer.capacity());

        while (buffer.remaining() > 0) {
            System.out.println(buffer.get());
        }
    }
}
